<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<title>fullpage2</title>
		<style type="text/css">
			* {box-sizing: border-box;}
			body, ul {margin: 0; padding: 0;}
			#fullpage {}
			#fullpage .inner {position: relative; overflow: hidden;}
			#fullpage .inner ul {position: relative; width: 100%;}
			#fullpage .item {width: 100%; font-size: 5em; color: #eee; line-height: 667px; text-align: center;}
			.i1 {background-color: #2AC845;}
			.i2 {background-color: #007AFF;}
			.i3 {background-color: #555555;}
			@keyframes breath{
				0% {bottom: 38px;}
				25% {bottom: 26px;}
				50% {bottom: 38px;}
				75% {bottom: 50px;}
				100% {bottom: 38px;}
			}
			.inner .narrow {position: absolute; bottom: 38px; left: 50%; transform: translateX(-50%); width: 50px; height: 40px; animation: breath 2s linear infinite;}
			.clone1 {position: absolute;}
			.clone2 {position: absolute; top: -667px;}
		</style>
	</head>
	<body>
		<div id="fullpage">
			<div class="inner">
				<ul class="list">
					<li class="item i1">1</li>
					<li class="item i2">2</li>
					<li class="item i3">3</li>
				</ul>
				<div class="narrow">
					<svg viewBox="0,0,50,50" fill="transparent" class="up">
						<path d="M0 10 L25 36 L50 10" stroke="#eee" stroke-width="3px"></path>
					</svg>
					<svg viewBox="0,0,50,50" fill="transparent" class="dw">
						<path d="M0 36 L25 10 L50 36" stroke="#eee" stroke-width="3px"></path>
					</svg>
				</div>
			</div>
		</div>
		
		<script type="text/javascript">
			// dom获取
			var getdom = function(ele) {
				if(ele == '') return;
				var ret;
				if(/([.])+/.test(ele)) {
					ret = document.querySelectorAll(ele);
				}else if(/([#])+/.test(ele)) {
					ret = document.querySelector(ele);
				}else if(/([.*])?/.test(ele)) {
					ret = document.querySelectorAll(ele);
				}
				return ret;
			};
			window.onload = function() {
				function Slider(opts) {
					var opts = typeof opts === 'object' ? opts : {};
					var	containerH = getdom(opts.el).offsetHeight,
					    innerH = (containerH >= window.innerHeight) ? window.innerHeight : containerH,  // 可视区高度
						inner = getdom(opts.el + ' .inner'),
						item = getdom(opts.el + ' .item'),
						ul = getdom(opts.el + ' .list'),
						up = getdom(opts.el + ' .narrow .up'),
						dw = getdom(opts.el + ' .narrow .dw'),
						index = 0,
						totalOffset = innerH * index;
					/**
					 * @des 初始化
					 */
					function _init() {
						ul[0].style.top = totalOffset + 'px';
						dw[0].style.display = 'none';
						inner[0].style.height = innerH + 'px';
						for(var i=0,l=item.length; i<l; i++) {
							item[i].style.height = innerH + 'px';
						}
						ul[0].style.height = (innerH * item.length) + 'px';
						
						new Dom(item);
						
						new Swipe();
					}
						
					/**
					 * @des DOM树重构，以实现loop
					 */
					function Dom(ele) {
						this.ele = ele;
						this.tagName = this.ele[0].nodeName.toLowerCase();
						this.props1 = {};
						this.props2 = {};
						var attrArr1 = [].slice.call(this.ele[0].attributes),
							attrArr2 = [].slice.call(this.ele[ele.length - 1].attributes),
							me = this, nodeArr = [];
						attrArr1.forEach(function(item, i) {
							me.props1[item.nodeName] = item.nodeValue + ' clone1';
						})
						attrArr2.forEach(function(item, i) {
							me.props2[item.nodeName] = item.nodeValue + ' clone2';
						})
						
						this.children1 = this.ele[0].innerHTML;
						this.children2 = this.ele[ele.length - 1].innerHTML;
						
						var eleLast = this.fragment(this.tagName, this.props1, this.children1);
						ul[0].appendChild(eleLast);
						var eleFirst = this.fragment(this.tagName, this.props2, this.children2);
						ul[0].insertBefore(eleFirst, item[0]);
					}
					// DOM树构建函数
					Dom.prototype.fragment = function(tagName, props, children) {
						var fragment = document.createDocumentFragment();
						var tag = document.createElement(tagName);
						for(var propName in props) {
							tag.setAttribute(propName, props[propName]);
						}
						tag.innerHTML = children;
						fragment.appendChild(tag);
						return fragment;
					}
					/**
					 * @des 滑动操作
					 */
					function Swipe() {
						var startY, moveY, endY, me = this;
						document.addEventListener('touchstart', function(e) {
							startY = e.changedTouches[0].pageY;
						}, false);
						document.addEventListener('touchmove', function(e) {
							moveY = e.changedTouches[0].pageY;
							h(startY, moveY);
						}, false);
						document.addEventListener('touchend', function(e) {
							endY = e.changedTouches[0].pageY;
							y(startY, endY)
						}, false);
						function h(s,m) {
							if(m - s > 0) {
								me.swipeDown(m-s);
							}else {
								me.swipeUp(m-s);
							}
						}
						function y(s,e) {
							if(e - s < 0) {
								me.swipeU()
							}else {
								me.swipeD();
							}
						}
					}
					Swipe.prototype = {
						swipeUp(m) {
							if(index >= item.length-1) return;
							totalOffset = -innerH * index + m;
							ul[0].style.top = totalOffset + 'px';
						},
						swipeDown(m) {
							if(index === 0) return;
							totalOffset = -innerH * index + m;
							ul[0].style.top = totalOffset + 'px';
						},
						swipeU() {
							if(index >= item.length) {
								// ul归位
								index = 0;
								totalOffset = -innerH * index;
								ul[0].style.top = totalOffset + 'px';
							};
							index++;
							if(index >= item.length-1) {
								up[0].style.display = 'none';
								dw[0].style.display = 'block';
							}
							var timer = setInterval(function() {
								if(innerH * index + totalOffset <= 1) {
									totalOffset = -innerH*index;
									ul[0].style.top = totalOffset + 'px';
									clearInterval(timer);
									return;
								}else {
									totalOffset += -(innerH*index + totalOffset)/10;
									ul[0].style.top = totalOffset + 'px';
								}
							}, 20);
						},
						swipeD() {
							if(index === 0) {
								// ul归位
								index = 3;
								totalOffset = -innerH * index;
								ul[0].style.top = totalOffset + 'px';
							};
							index--;
							if(index === 0) {
								dw[0].style.display = 'none';
								up[0].style.display = 'block';
							}
							var timer = setInterval(function() {
								if(-totalOffset - innerH * index <= 1) {
									totalOffset = -innerH * index;
									ul[0].style.top = totalOffset + 'px';
									clearInterval(timer);
									return;
								}else {
									totalOffset += -(innerH*index + totalOffset)/10;
									ul[0].style.top = totalOffset + 'px';
								}
							}, 20);
						}
					}
					_init();
				}
				new Slider({
					el: '#fullpage',
				})
			}
		</script>
	</body>
</html>

